package com.atguigu.gulimall.auth.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.utils.HttpUtils;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.auth.feign.MemberFeignService;
import com.atguigu.common.vo.MemberResponseVo;
import com.atguigu.gulimall.auth.vo.SocialUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;

import static com.atguigu.common.constant.AuthServerConstant.LOGIN_USER;

/**
 * 处理社交登录请求
 */
@Slf4j
@Controller
public class OAuth2Controller {
    @Resource
    private MemberFeignService memberFeignService;


    /**
     * 社交登录成功回调
     * @param code 用户同意授权(输入自己的账号密码后),页面会跳转到你设置的重定向的那个地址,还会带个code,我们可以用code去换取token
     * @param session
     * @param servletResponse 注意啊,是servletResponse,跟HttpUtils那个response区分开
     * @return
     * @throws Exception
     */
    @GetMapping(value = "/oauth2.0/weibo/success")
    public String weibo(@RequestParam("code") String code, HttpSession session, HttpServletResponse servletResponse) throws Exception {

        Map<String, String> map = new HashMap<>();
        // 下面的信息见谷粒商城工具的使用6社交登录使用步骤postman测试
        map.put("client_id", "2077705774");// 就微博那个App Key
        map.put("client_secret", "40af02bd1c7e435ba6a6e9cd3bf799fd");// 微博的App Secret
        map.put("grant_type", "authorization_code");// 授权方式,微博那个链接自带的,应该是写死的
        map.put("redirect_uri", "http://auth.gulimall.com/oauth2.0/weibo/success");// 授权成功后重定向的地址
        map.put("code", code);// code码,用来换取token

        /**
         * 1、根据用户授权返回的code换取access_token
         * 工具类发一个post请求,注意,请求的方式看人家的开发文档,要么就穷举法,几种请求方式一个一个试
         * 主机地址:http就是微博api.weibo.com
         * 请求路径:/oauth2/access_token  就是获取token的路径
         * 请求方式:post方式
         * 请求头:new HashMap<>()
         * 查询参数:map
         * 请求体:new HashMap<>()
         */
        HttpResponse response = HttpUtils.doPost("https://api.weibo.com", "/oauth2/access_token", "post", new HashMap<>(), map, new HashMap<>());

        //2、处理
        if (response.getStatusLine().getStatusCode() == 200) {// 工具类只要会用就可以了,如果响应码是200说明成功了
            //获取到了access_token,转为通用社交登录对象 响应体内容变成json
            String json = EntityUtils.toString(response.getEntity());// 这是阿帕奇的一个工具类,将HttpEntity(就是response.getEntity()获取的实体)这个实体类转换成字符串
            SocialUser socialUser = JSON.parseObject(json, SocialUser.class);

            //知道当前是哪个社交用户
            //1）、当前用户如果是第一次进网站，自动注册进来（为当前社交用户生成一个会员信息，以后这个社交账号就对应指定的会员）
            //登录(第一次之后)  或者  注册(第一次)  这个社交用户
            System.out.println(socialUser.getAccess_token());
            //调用远程服务
            R oauthlogin = memberFeignService.oauthlogin(socialUser);
            if (oauthlogin.getCode() == 0) {
                MemberResponseVo data = oauthlogin.getData("data", new TypeReference<MemberResponseVo>() {
                });
                log.info("登录成功：用户信息：{}", data.toString());

                //1、第一次使用session，命令浏览器保存卡号，JSESSIONID这个cookie
                //以后浏览器访问哪个网站就会带上这个网站的cookie
                //TODO 1、默认发的令牌。当前域（解决子域session共享问题）
                //TODO 2、使用JSON的序列化方式来序列化对象到Redis中
                session.setAttribute(LOGIN_USER,data);

                //2、只要换取到了access_token,就说明登录成功,登录成功跳回首页
                return "redirect:http://gulimall.com";
            } else {

                return "redirect:http://auth.gulimall.com/login.html";
            }

        } else {
            // 失败了,没有换取到token，重定向到登录页
            return "redirect:http://auth.gulimall.com/login.html";
        }

    }

}